[AngularJS] UI.Sortable を使ったドラッグ&ドロップ UI の構築
車輪開発大好きおたいがです。こんにちは。( 挨拶 )
AngularUI プロジェクトには UI.Sortable というサブプロジェクトがあります。このプロジェクトは jQuery UI Sortable を AngularJS 用にカスタマイズしたものが置かれていますが、その中の一例を実務で採用したので使用方法をまとめておきました。
導入
bower または npm でソースを取得します。
bower install -S angular-ui-sortable
npm install -S angular-ui-sortable
( -S は --save と同義 )
依存関係
- jQuery
- jQueryUI 1.9+
- AngularJS v1.2+
jQuery, jQueryUI が必要になるので <script> 要素の記述を忘れないように気を付けましょう。
定義
bower で導入したときの例 (HTML)
jQuery, jQueryUI, AngularJS …の定義順で。
<script src="bower_components/jquery/dist/jquery.min.js"></script> <script src="bower_components/jquery-ui/jquery-ui.min.js"></script> <script src="bower_components/angular/angular.min.js"></script> … <script src="bower_components/angular-ui-sortable/sortable.min.js"></script>
モジュールの定義 (JavaScript)
ui.sortable モジュールを導入します。
angular.module('sampleApp', ['ui.sortable', …], function(…)
実装例
tbody の行をドラッグ&ドロップするサンプルを例に説明を進めます。
ドラッグさせたい要素の親要素にて ui-sortable 属性値を定義します。このとき親子関係を保つ必要があります。 ( 先祖-子孫関係では動作に不具合が生じるので注意が必要です ) 属性値には jQuery UI Sortable の全オプションを定義することが可能です。
ドラッグのつまみ役を担う DOM のセレクタ名を設定する handle プロパティや、開始、終了時のハンドラ ( 関数 ) を設定する start stop プロパティは使用頻度が高いものと思われます。
HTML
<tbody ui-sortable="ctrl.sortableOptions"> <tr ng-repeat="item in ctrl.items"> <td class="drag-cursor" data-js="drag__handle"> <span class="glyphicon glyphicon-menu-hamburger"></span> </td> <td>{{item.label}}</td> </tr> </tbody>
CSS
.drag-cursor { cursor: move; }
JavaScript
ctrl.sortableOptions = { 'handle' : '[data-js=drag__handle]', 'axis ' : 'y', 'start' : function(event, ui) { ui.item.startPos = ui.item.index(); }, 'stop' : function(event, ui) { var startPos = ui.item.startPos; var endPos = ui.item.index(); if(!angular.equals(startPos, endPos)) { var rowData = ctrl.items[startPos]; ctrl.items.splice(startPos, 1); ctrl.items.splice(endPos, 0, rowData); $scope.$apply(); } } };
サンプル
お手製サンプル
一覧の左列のアイコンをドラッグ&ドロップすることで、行を入れ替えてデータを差し替えるサンプルを作成しました。
その他、公式のサンプル
上記サンプル以外にも、たくさんのサンプルが用意されているので興味のある方はどうぞ。
https://github.com/angular-ui/ui-sortable#user-content-examples
さいごに
意外少量のコードでドラッグ&ドロップが実現できることが伝われば幸いですが、実際は実装コード本体よりも CSS の細かい設定の方が面倒に個人的には思えまして、組み込むことにはあまり積極的になれません ( 苦笑